package com.bang.daybreak.common.util;

import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.Temporal;
import java.util.Calendar;
import java.util.Date;

/**
 * 时间工具类java8
 *
 * @author : wdj
 * @since : 2019/1/10 0010 下午 14:30
 * @version 1.0
 */
public class DateUtil {

    /**
     * yyyyMMddHHmmss
     */
    public static final DateTimeFormatter FORMAT_DATETIME_STAMP = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
    /**
     * yyyy-MM-dd HH:mm:ss
     */
    public static final DateTimeFormatter FORMATTER_YYYY_MM_DD = DateTimeFormatter.ofPattern("yyyy-MM-dd");


    /**
     * yyyy-MM-dd HH:mm:ss
     */
    public static final DateTimeFormatter FORMATTER_DATETIME = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    public static final String FORMAT_YMDHMS = "yyyy-MM-dd HH:mm:ss";

    /**
     * 获取当前日期
     *
     * @return YYYY-MM-DD
     */
    public static LocalDate getLocalDate() {
        return LocalDate.now();
    }

    /**
     * 获取当前时间
     *
     * @return
     */
    public static LocalTime getLocalTime() {
        return LocalTime.now();
    }

    /**
     * 获取当前日期时间
     *
     * @return
     */
    public static LocalDateTime getLocalDateTime() {
        return LocalDateTime.now();
    }

    /**
     * 获取当前的微秒数
     *
     * @return
     */
    public static long getClockMillis() {
        Clock clock = Clock.systemDefaultZone();
        return clock.millis();
    }

    /**
     * 返回当前时间yyyyMMddHHmmss
     *
     * @return
     */
    public static String getDateTimestamp() {
        return getLocalDateTime().format(FORMAT_DATETIME_STAMP);
    }

    /**
     * 返回当前时间yyyy-MM-dd
     *
     * @return
     */
    public static String getDate() {
        return getLocalDate().format(DateTimeFormatter.ISO_LOCAL_DATE);
    }

    /**
     * 返回当前系统时间 yyyy-MM-dd HH:mm:ss
     *
     * @return 返回当前系统时间
     */
    public static String getDateTime() {
        return getLocalDateTime().format(FORMATTER_DATETIME);
    }

    /**
     * 获取当月第一天 yyyy-MM-dd
     *
     * @return
     */
    public static String getFirstDayOfMonth() {
        return getLocalDate().withDayOfMonth(1).format(DateTimeFormatter.ISO_LOCAL_DATE);
    }

    /**
     * 获取本月最后一天 yyyy-MM-dd
     *
     * @return
     */
    public static String getLastDayOfMonth() {
        LocalDate localDate = getLocalDate();
        return localDate.withDayOfMonth(localDate.lengthOfMonth()).format(DateTimeFormatter.ISO_LOCAL_DATE);
    }

    /**
     * 将yyyyMMddHHmmss转为 yyyy-MM-dd HH:mm:ss
     *
     * @param dateTimestamp
     * @return
     */
    public static String formatDateTimestamp(String dateTimestamp) {
        return LocalDateTime.parse(dateTimestamp, FORMAT_DATETIME_STAMP).format(FORMATTER_DATETIME);
    }

    /**
     * 将yyyy-MM-dd HH:mm:ss转为 yyyyMMddHHmmss
     */
    public static String formatDateTime(String dateTime) {
        return parseLocalDateTime(dateTime).format(FORMAT_DATETIME_STAMP);
    }

    /**
     * 将yyyy-MM-dd HH:mm:ss转为 LocalDateTime
     */
    public static LocalDateTime parseLocalDateTime(String dateTime) {
        return LocalDateTime.parse(dateTime, FORMATTER_DATETIME);
    }

    /**
     * 将yyyyMMddHHmmss转为 LocalDateTime
     */
    public static LocalDateTime parseLocalDateTimestamp(String dateTimestamp) {
        return LocalDateTime.parse(dateTimestamp, FORMAT_DATETIME_STAMP);
    }

    /**
     * yyyy-MM-dd字符串转LocalDate
     *
     * @param dateString
     * @return
     */
    public static LocalDate parseLocalDate(String dateString) {
        return LocalDate.parse(dateString, DateTimeFormatter.ISO_LOCAL_DATE);
    }

    /**
     * yyyy-MM-dd 增加日期
     *
     * @param date
     * @param days
     * @return
     */
    public static String plusDays(String date, int days) {
        LocalDate localDate = parseLocalDate(date);
        return localDate.plusDays(days).format(DateTimeFormatter.ISO_LOCAL_DATE);
    }

    /**
     * 计算两个日期之间相差的天数
     *
     * @param startDate 较小的时间 yyyy-MM-dd
     * @param endDate   较大的时间 yyyy-MM-dd
     * @return 相差天数
     */
    public static int dateCompareTo(String startDate, String endDate) {
        LocalDate startLocalDate = LocalDate.parse(startDate, DateTimeFormatter.ISO_LOCAL_DATE);
        LocalDate endLocalDate = LocalDate.parse(endDate, DateTimeFormatter.ISO_LOCAL_DATE);
        Period period = Period.between(startLocalDate, endLocalDate);
        return period.getDays();
    }

    /**
     * LocalDateTime转换为Date
     *
     * @param localDateTime
     */
    public static Date localDateTimeToDate(LocalDateTime localDateTime) {
        ZoneId zoneId = ZoneId.systemDefault();
        ZonedDateTime zdt = localDateTime.atZone(zoneId);
        return Date.from(zdt.toInstant());
    }

    /**
     * LocalDateTime转换为yyyy-mm-dd
     *
     * @param localDateTime
     */
    public static String localDateTimeToYmd(LocalDateTime localDateTime) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        return df.format(localDateTime);
    }

    /**
     * LocalDateTime转换为yyyy-MM-dd HH:mm:ss
     *
     * @param localDateTime
     */
    public static String localDateTimeToYmdhms(LocalDateTime localDateTime) {
        if (null == localDateTime) {
            return null;
        }
        return FORMATTER_DATETIME.format(localDateTime);
    }

    /**
     * Date转换为LocalDateTime
     *
     * @param date
     */
    public static LocalDateTime dateToLocalDateTime(Date date) {
        //An instantaneous point on the time-line.(时间线上的一个瞬时点。)
        Instant instant = date.toInstant();
        //A time-zone ID, such as {@code Europe/Paris}.(时区)
        ZoneId zoneId = ZoneId.systemDefault();
        return instant.atZone(zoneId).toLocalDateTime();
    }


    /**
     * Date 转 LocalDateTime
     *
     * @param date
     * @return LocalDate
     */
    public static LocalDate dateToLocalDate(Date date) {
        Instant instant = date.toInstant();
        //A time-zone ID, such as {@code Europe/Paris}.(时区)
        ZoneId zoneId = ZoneId.systemDefault();

        return instant.atZone(zoneId).toLocalDate();
    }

    /**
     * 根据时间获取当月有多少天数
     *
     * @param date
     * @return
     */
    public static int getThisMonthDays(Date date) {
        return dateToLocalDateTime(date).getMonth().length(dateToLocalDate(date).isLeapYear());
    }

    /**
     * 比较两个LocalDateTime是否同一天
     *
     * @param begin
     * @param end
     * @return
     */
    public static boolean isTheSameDay(LocalDateTime begin, LocalDateTime end) {
        return begin.toLocalDate().equals(end.toLocalDate());
    }

    /**
     * 日期相隔天数
     *
     * @param startTime
     * @param endTime
     * @return
     */
    public static long periodDays(LocalDate startTime, LocalDate endTime) {
        return endTime.toEpochDay() - startTime.toEpochDay();
    }

    /**
     * 日期相隔小时
     *
     * @param startTime
     * @param endTime
     * @return
     */
    public static long durationHours(Temporal startTime, Temporal endTime) {
        return Duration.between(startTime, endTime).toHours();
    }

    /**
     * 日期相隔分钟
     *
     * @param startTime
     * @param endTime
     * @return
     */
    public static long durationMinutes(Temporal startTime, Temporal endTime) {
        return Duration.between(startTime, endTime).toMinutes();
    }

    /**
     * 日期相隔毫秒数
     *
     * @param startInclusive
     * @param endExclusive
     * @return
     */
    public static long durationMillis(Temporal startInclusive, Temporal endExclusive) {
        return Duration.between(startInclusive, endExclusive).toMillis();
    }

    /**
     * 是否当天
     *
     * @param date
     * @return
     */
    public static boolean isToday(LocalDate date) {
        return getLocalTime().equals(date);
    }

    /**
     * clj
     * date型格式时间加减相应月数,并返回yyyy-MM-dd HH:mm:ss格式时间
     * @param dateTime date型格式时间
     * @param month 月数
     * @return yyyy-MM-dd HH:mm:ss格式时间
     */
    public static String parseDateymdhms(Date dateTime, int month) {
        if (null == dateTime) {
            return null;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(dateTime);
        cal.add(Calendar.MONTH, month);
        SimpleDateFormat sdfymd = new SimpleDateFormat(FORMAT_YMDHMS);
        return sdfymd.format(cal.getTime());
    }

    /**
     * @author bingo
     * date型格式时间加减相应天数,并返回yyyy-MM-dd HH:mm:ss格式时间
     * @param dateTime date型格式时间
     * @param day 天数
     * @return yyyy-MM-dd HH:mm:ss格式时间
     */
    public static String parseDateSubDay(Date dateTime, int day) {
        if (null == dateTime) {
            return null;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(dateTime);
        cal.add(Calendar.DATE, day);
        SimpleDateFormat sdfymd = new SimpleDateFormat(FORMAT_YMDHMS);
        return sdfymd.format(cal.getTime());
    }

}
